#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/covariance.hpp>
#include <boost/accumulators/statistics/variates/covariate.hpp>

#include <boost/accumulators/framework/accumulator_base.hpp>
#include <boost/accumulators/framework/parameters/sample.hpp>

namespace boost {
    // Putting your accumulators in the
    namespace accumulators {
        // impl namespace has some
        namespace impl {
            // advantages. See below.
            template<typename Sample>
            struct sum_accumulator // All accumulators should inherit from
                    : accumulator_base // accumulator_base.
            {
                typedef Sample result_type; // The type returned by result() below.
                template<typename Args> // The constructor takes an argument pack.
                sum_accumulator(Args const &args)
                    : sum(args[sample | Sample()]) // Maybe there is an initial value in the
                {
                    // argument pack. ('sample' is defined in
                } // sample.hpp, included above.)
                template<typename Args> // The accumulate function is the function
                void operator ()(Args const &args) // call operator, and it also accepts an
                {
                    // argument pack.
                    this->sum += args[sample];
                }

                result_type result(dont_care) const // The result function will also be passed
                {
                    // an argument pack, but we don't use it here,
                    return this->sum; // so we use "dont_care" as the argument type.
                }

            private:
                Sample sum;
            };
        }
    }
}

namespace xk_accumulators {
    using namespace boost::accumulators;
    //累加器权重学习 权重放在第三个参数位
    void weight_sample() {
        accumulator_set<int, features<tag::sum>, int> acc;
        acc(1, weight = 2);
        acc(2, weight = 3);
        std::cout << sum(acc) << std::endl;
    }

    //min max 测试提取器 extractor<tag::max>
    void extract_sample() {
        accumulator_set<int, features<tag::min, tag::max> > acc;
        acc(1);
        acc(2);
        acc(3);
        acc(5);
        std::cout << extract_result<tag::min>(acc) << std::endl;
        extractor<tag::max> max_;
        std::cout << max_(acc) << std::endl;
    }

    //协变量
    void tag_covariatel() {
        typedef tag::tail_variate<int, tag::covariate1, right> my_tail_variate_tag;
        accumulator_set<double, features<my_tail_variate_tag> > acc(tag::tail<right>::cache_size = 2);
        acc(1.2, covariate1 = 12);
        acc(2.3, covariate1 = -23);
        acc(3.4, covariate1 = 34);
        acc(4.5, covariate1 = -45);
        //定义提取
        extractor<my_tail_variate_tag> my_extractor;
        std::ostream_iterator<double> dout(std::cout, ", ");
        std::copy(tail(acc).begin(), tail(acc).end(), dout);
        std::ostream_iterator<int> iout(std::cout, ", ");
        std::copy(my_extractor(acc).begin(), my_extractor(acc).end(), iout);
    }

    // 定义变参模板函数来打印任意数量和类型的参数
    template<typename... Args>
    void print(const Args &... args) {
        // 使用初始化列表和逗号表达式
        (void)std::initializer_list<int>{(std::cout << args << ' ', 0)...};
        std::cout << std::endl; // 打印换行
    }
}

int main() {
    xk_accumulators::print(1, "12", "hello world", new int[]{1});
    return 0;
}
